﻿using BuildStatus.Web.Models;
using Microsoft.TeamFoundation.Build.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Client = Microsoft.TeamFoundation.Build.Client;

namespace BuildStatus.Web.BuildServer
{
    public class BuildWatcher
    {
        private readonly TimeSpan RefreshTime = new TimeSpan(0, 0, 5);

        private static BuildWatcher _instance;
        private static object _lock = new object();

        private System.Threading.Timer _refreshTimer;

        private IBuildStatusServer _buildServer;
        private List<BuildProject> _currentBuildProjects = new List<BuildProject>();

        public static BuildWatcher Instance
        {
            get
            {
                lock (_lock)
                {
                    if (_instance == null)
                        _instance = new BuildWatcher();

                    return _instance;
                }
            }
        }

        private BuildWatcher()
        {
            _refreshTimer = new System.Threading.Timer(new System.Threading.TimerCallback(RefreshCallback), this, new TimeSpan(0, 0, 1), RefreshTime);
        }

        private bool _inCallback = false;
        private void RefreshCallback(object state)
        {
            // _currentBuildProjects = GenerateDemoBuilds();
            // return;
            if (_inCallback)
                return;

            try
            {
                _inCallback = true;

                List<BuildProject> newProjects = new List<BuildProject>();

                BuildWatcher watcher = (BuildWatcher)state;
                try
                {
                    if (watcher._buildServer == null)
                        watcher._buildServer = GetBuildServer();

                    newProjects = watcher._buildServer.GetBuildProjects().ToList();
                }
                catch (Exception ex)
                {
                    watcher._buildServer = null;
                }

                lock (_lock)
                {
                    _currentBuildProjects = newProjects;
                }
            }
            finally
            {
                _inCallback = false;
            }
        }

        public List<BuildProject> GetBuildProjects()
        {
            lock (_lock)
            {
                return _currentBuildProjects;
            }
        }

        public BuildLog GetBuildLog(string buildNumber)
        {
            using (IBuildStatusServer tmpServer = GetBuildServer())
            {
                return tmpServer.GetBuildLog(buildNumber);
            }
        }

        public void RetryBuild(string buildNumber)
        {
            using (IBuildStatusServer tmpServer = GetBuildServer())
            {
                tmpServer.RetryBuild(buildNumber);
            }
        }

        private IBuildStatusServer GetBuildServer()
        {
            if (BuildSettings.Settings.UseRestAPI)
                return new BuildServerRestAPI();

            return new BuildServer();
        }

        private static List<BuildProject> GenerateDemoBuilds()
        {
            List<BuildProject> result = new List<BuildProject>();

            // result.Add(new BuildDefinition() { Name = "" });
            BuildProject buildProject = new BuildProject() { Name = "Sample Team Project" };
            buildProject.Builds.Add(new BuildDefinition() { Name = "Dev build", DisplayClass = Client.BuildStatus.Succeeded.ToString(), Status = Client.BuildStatus.Succeeded.ToString(), RequestedBy = "Neo", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "04:30", BuildNumber = "1", IsWaiting = false });
            buildProject.Builds.Add(new BuildDefinition() { Name = "Release build 1.0.0.0", DisplayClass = Client.BuildStatus.Succeeded.ToString(), Status = Client.BuildStatus.Succeeded.ToString(), RequestedBy = "Neo", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "02:14", BuildNumber = "2", IsWaiting = false });
            buildProject.Builds.Add(new BuildDefinition() { Name = "Release build 1.1.0.0", DisplayClass = Client.BuildStatus.Succeeded.ToString(), Status = Client.BuildStatus.Succeeded.ToString(), RequestedBy = "Neo", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "05:54", BuildNumber = "3", IsWaiting = false });
            buildProject.Builds.Add(new BuildDefinition() { Name = "Release build 1.2.0.0", DisplayClass = Client.BuildStatus.Succeeded.ToString(), Status = Client.BuildStatus.Succeeded.ToString(), RequestedBy = "Neo", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "04:13", BuildNumber = "4", IsWaiting = false });
            result.Add(buildProject);


            buildProject = new BuildProject() { Name = "Another Team Project" };
            buildProject.Builds.Add(new BuildDefinition() { Name = "Master build", DisplayClass = Client.BuildStatus.InProgress.ToString(), Status = Client.BuildStatus.InProgress.ToString(), RequestedBy = "Morpheus", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "01:23", BuildNumber = "5", IsWaiting = false });
            buildProject.Builds.Add(new BuildDefinition() { Name = "Branch 1 build", DisplayClass = Client.BuildStatus.Failed.ToString(), Status = Client.BuildStatus.Failed.ToString(), RequestedBy = "Morpheus", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "01:56", BuildNumber = "6", IsWaiting = false });
            buildProject.Builds.Add(new BuildDefinition() { Name = "Branch 2 build", DisplayClass = Client.BuildStatus.Stopped.ToString(), Status = Client.BuildStatus.Stopped.ToString(), RequestedBy = "Morpheus", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "02:34", BuildNumber = "7", IsWaiting = false });
            buildProject.Builds.Add(new BuildDefinition() { Name = "Branch 3 build", DisplayClass = Client.BuildStatus.PartiallySucceeded.ToString(), Status = Client.BuildStatus.PartiallySucceeded.ToString(), RequestedBy = "Morpheus", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "01:22", BuildNumber = "8", IsWaiting = false });
            buildProject.Builds.Add(new BuildDefinition() { Name = "Branch 4 build", DisplayClass = Client.BuildStatus.Succeeded.ToString(), Status = Client.BuildStatus.Succeeded.ToString(), RequestedBy = "Morpheus", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "05:35", BuildNumber = "9", IsWaiting = false });
            buildProject.Builds.Add(new BuildDefinition() { Name = "Branch 5 build", DisplayClass = QueueStatus.Queued.ToString(), Status = QueueStatus.Queued.ToString(), RequestedBy = "Morpheus", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "10:21", BuildNumber = "10", IsWaiting = true });
            result.Add(buildProject);


            buildProject = new BuildProject() { Name = "Third project" };
            buildProject.Builds.Add(new BuildDefinition() { Name = "Master build", DisplayClass = Client.BuildStatus.Succeeded.ToString(), Status = Client.BuildStatus.Succeeded.ToString(), RequestedBy = "Trinity", StartTime = DateTime.Now.ToString(BuildServer.DateTimeFormat), Duration = "01:23", BuildNumber = "11", IsWaiting = false });
            result.Add(buildProject);


            return result;
        }
    }
}
